<?php

namespace App\Exceptions;

use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of exception types with their corresponding custom log levels.
     *
     * @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
     */
    protected $levels = [
        //
    ];

    /**
     * A list of the exception types that are not reported.
     *
     * @var array<int, class-string<\Throwable>>
     */
    protected $dontReport = [
        ApiException::class,
        ApiHttpOkException::class,
    ];

    /**
     * A list of the inputs that are never flashed to the session on validation exceptions.
     *
     * @var array<int, string>
     */
    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    /**
     * Register the exception handling callbacks for the application.
     *
     * @return void
     */
    public function register()
    {
        // $this->reportable(function (Throwable $e) {
        //     logger(__METHOD__, [$e->getMessage()]);
        // });
        /*$this->reportable(function (AuthenticationException $e) {
            return responseException(__('auth.failed'), [], ApiException::CODE_AUTH_FAILED, 401)->send();
        })->stop();

        $this->reportable(function (ValidationException $e) {
            $message = array_values($e->errors())[0];
            info('request', request()->all());
            info(is_array($message) ? $message[0] : $message);
            return responseException(is_array($message) ? $message[0] : $message)->send();
        })->stop();

        $this->reportable(function (NotFoundHttpException $e) {
            return responseException('404 Not Found!', null, 404, 404)->send();
        })->stop();

        $this->reportable(function (ModelNotFoundException $e) {
            return responseException('数据不存在!', null, 404, 404)->send();
        })->stop();

        $this->reportable(function (ApiException $e) {
            return responseException($e->getMessage(), $e->getData(), $e->getCode())->send();
        });

        $this->reportable(function (\Exception $e) {
            return responseException('系统异常, 请稍后再试', null, 500, 500)->send();
        });*/
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param Throwable $e
     * @return false|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
     * @throws Throwable
     */
    public function render($request, Throwable $e)
    {
        // 非 API 接口不处理
        // if (!$request->is('api/*') && !$request->is('admin/*')) return parent::render($request, $e);

        if ($e instanceof AuthenticationException) {
            info('AuthenticationException', ['Url' => $request->url(), 'Authorization' => request()->header('Authorization')]);
            return responseException(__('auth.failed'), [], ApiException::CODE_AUTH_FAILED, 401);
        }

        if ($e instanceof ValidationException) {
            $message = array_values($e->errors())[0];
            info('request', request()->all());
            info(is_array($message) ? $message[0] : $message);
            return responseException(is_array($message) ? $message[0] : $message);
        }

        if ($e instanceof MethodNotAllowedHttpException) {
            return responseException($e->getMessage(), [], 405, 405);
        }

        if ($e instanceof NotFoundHttpException) {
            return new SymfonyResponse('', 404);
        }

        if ($e instanceof ModelNotFoundException) {
            return responseException('数据不存在!', null, 404, 404);
        }
        if ($e instanceof ApiException) {
            return responseException($e->getMessage(), $e->getData(), $e->getCode());
        }

        if ($e instanceof ApiHttpOkException) {
            return responseException($e->getMessage(), $e->getData(), $e->getCode(), 200);
        }

        if ($e instanceof TokenMismatchException) {
            return responseException('页面已过期, 请刷新后重试');
        }
        if ($e instanceof ThrottleRequestsException) {
            return responseException('操作太快, 停下来喝杯奶茶吧', [], 429, 429);
        }
        if ($e instanceof HttpException) {
            return responseException($e->getMessage(), '', $e->getStatusCode(), $e->getStatusCode());
        }
        // 调试模式直接抛出异常
        if (config('app.debug')) return parent::render($request, $e);

        // 记录未知异常, 并尝试记录上下文
        // info($e, [method_exists($e, 'context') ? $e->context() : '',]);

        // if ($e instanceof \Exception) {
        return responseException('网络拥堵, 请稍后再试', null, 500, 500);
        // }

        // return responseException(__('api.failed'), [], 500, 500);
    }
}
